package com.yaodian100.core.sms.service.impl;

import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.betwixt.io.BeanWriter;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.batch.service.BatchJobService;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.BaseManager;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.mail.entity.Mail;
import com.yaodian100.core.mail.service.MailService;
import com.yaodian100.core.menu.entity.Option;
import com.yaodian100.core.sms.entity.Sms;
import com.yaodian100.core.sms.service.SmsService;
import com.yaodian100.core.template.service.TemplateService;

public class SmsServiceImpl extends DomainServiceImpl<Sms> implements SmsService {
	@Autowired
	BatchJobService batchJobService;

	@Resource
	private JdbcTemplate jdbcTemplate;
	@Resource
	private BaseManager baseMgr;

	@Autowired
	private TemplateService templateService;
	@Autowired
	private MailService mailService;
	private static final String VM_SMS_EXCEPTION_NOTIFICATION = "smsExeceptionNotification";

	@Transactional(readOnly = false)
	public boolean updateSmsResponse(Long msgId, String smsId, String responseCode, String reasonCode,
			String responseMessage, Date responseTime) {
		return this.updateSmsResponse(msgId, smsId, responseCode, reasonCode, responseMessage, responseTime, null);
	}

	@Transactional(readOnly = false)
	public boolean receiveSmsDeliveryReport(String smsId, String statusCode, Date receiveTime, Date operatorTime,
			String reasonCode, String statusText) {
		return this.receiveSmsDeliveryReport(smsId, statusCode, receiveTime, operatorTime, reasonCode, statusText, null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.core.sms.service.SmsService#receiveSmsDeliveryReport(java.lang.String, java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public boolean receiveSmsDeliveryReport(String smsId, String statusCode, Date receiveTime, Date operatorTime,
			String reasonCode, String statusText, String operator) {

		CommonCriteria cc = new CommonCriteria();
		cc.addEq("smsId", smsId);
		int failCount = 0;

		List<Sms> smses = getDao().getList(cc, null);
		for (Sms sms : smses) {
			sms.setStatus("2");
			sms.setStatusCode(statusCode);
			sms.setReceiveTime(receiveTime);
			sms.setOperatorTime(operatorTime);
			sms.setReceiveReasonCode(reasonCode);
			sms.setStatusText(statusText);
			if (StringUtils.isNotBlank(sms.getOperator())) {
				sms.setOperator(operator);
			}
			sms = update(sms);

			if (!"2".equals(sms.getStatus()))
				failCount++;
		}

		if (failCount > 0)
			return false;
		else
			return true;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.core.sms.service.SmsService#sendSms(java.lang.String, java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void sendSms(String caller, String smsMsg, String orderId) {
		ArrayList<String> msgBodies = new ArrayList<String>();

		if (!caller.startsWith("86") && !caller.startsWith("886")) {
			if (caller.startsWith("09")) {// 台灣號碼未加國碼
				caller = "886".concat(caller.substring(1));
			} else {
				caller = "86".concat(caller);
			}
		}

		StringUtils.replace(caller, " ", "");
		StringUtils.replace(caller, "-", "");

		int sendBeginIndex = 0;
		int maxMessageLength = 200;
		while (sendBeginIndex < smsMsg.length()) {
			int sendEndIndex = 0;
			if (sendBeginIndex + maxMessageLength < smsMsg.length()) {
				sendEndIndex = sendBeginIndex + maxMessageLength;
			} else {
				sendEndIndex = smsMsg.length();
			}
			msgBodies.add(smsMsg.substring(sendBeginIndex, sendEndIndex));
			sendBeginIndex = sendBeginIndex + maxMessageLength;
		}
		int totalMsg = msgBodies.size();
		int msgCount = 1;

		for (Iterator<String> it = msgBodies.iterator(); it.hasNext();) {
			String headNumber = "";
			if (totalMsg > 1) {
				headNumber = "(" + msgCount + "/" + totalMsg + ") ";
				msgCount++;
			}
			String msgBody = it.next();
			Sms sms = new Sms();
			sms.setStatus("0");
			sms.setDestAddress(caller);
			sms.setContent(headNumber + msgBody);
			sms.setOrderId(orderId);
			super.save(sms);

			batchJobService.save("EC-SendSMS", toXML(sms), null, orderId);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.core.sms.service.SmsService#updateSmsResponse(java.lang.String, java.lang.String,
	 * java.lang.String, java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public boolean updateSmsResponse(Long msgId, String smsId, String responseCode, String reasonCode,
			String responseMessage, Date responseTime, String operator) {
		boolean result = false;

		Sms sms = getDao().get(msgId);
		if (null != sms) {
			sms.setStatus("1");
			sms.setSmsId(smsId);
			sms.setResponseTime(responseTime);
			sms.setResponseCode(responseCode);
			sms.setResponseReasonCode(reasonCode);
			sms.setResponseMessage(responseMessage);
			sms.setOperator(operator);

			sms = update(sms);

			if ("1".equals(sms.getStatus())) {
				result = true;
			}
		}
		return result;

	}

	private String toXML(Sms entity) throws CoreException {
		String xml = null;
		try {

			StringWriter sw = new StringWriter();
			BeanWriter beanWriter = new BeanWriter(sw);
			beanWriter.enablePrettyPrint();
			beanWriter.getBindingConfiguration().setMapIDs(false);
			beanWriter.write(entity);
			xml = sw.toString();
			beanWriter.flush();
			beanWriter.close();
		} catch (Exception e) {
			logger.info("to XML Exception:{}", e);

		}
		return xml;
	}

	@Override
	@Transactional(readOnly = false)
	public List<Sms> queryEmergencySmsByDate(String date) {
		List<Sms> msg = null;
		try {
			Date setDate = new SimpleDateFormat("yyyyMMdd").parse(date);
			Calendar calS = Calendar.getInstance();
			Calendar calE = Calendar.getInstance();
			calS.setTime(setDate);
			calS.set(Calendar.HOUR_OF_DAY, 0);
			calS.set(Calendar.MINUTE, 0);
			calS.set(Calendar.SECOND, 0);

			calE.setTime(setDate);
			calE.set(Calendar.HOUR_OF_DAY, 23);
			calE.set(Calendar.MINUTE, 59);
			calE.set(Calendar.SECOND, 59);

			CommonCriteria cc = new CommonCriteria();
			// cc.addEq("orderId", "SOS");
			cc.addRlike("orderId", "SOS");
			cc.addGe("createDate", calS.getTime());
			cc.addLe("createDate", calE.getTime());
			msg = getDao().getList(cc, new String[] { "orderId desc", "msgId asc" });
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return msg;

	}

	@Override
	@Transactional(readOnly = false)
	public List<Sms> querySmsByOrderId(String orderId) {
		List<Sms> msg = null;
		try {

			CommonCriteria cc = new CommonCriteria();
			cc.addEq("orderId", orderId);
			msg = getDao().getList(cc, new String[] { "orderId desc", "msgId asc" });
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return msg;

	}

	@Override
	@Transactional(readOnly = false)
	public List<Map<String, Object>> getSmsExceptionData() {

		StringBuffer sql = new StringBuffer();
		sql.append("select a.msg_id,a.create_date,a.destination_address,a.content,a.status,b.job_id,b.job_status ");
		sql.append("from comm_sms a,( ");
		sql.append("select job_id,create_date,job_status, ");
		sql.append("to_number(substr(trim(bean_parm), ");
		sql.append("INSTR(trim(bean_parm),' <msgId>')+8, ");
		sql.append("(INSTR(trim(bean_parm),'</msgId>')-INSTR(trim(bean_parm),' <msgId>')-8)),'999999') \"msg_id\" ");
		sql.append("from ( ");
		sql.append("select job_id,create_date,job_status,bean_parm from comm_batchjob ");
		sql.append("where bean_id = 'EC-SendSMS' and ");
		sql.append("create_date > sysdate -5 and ");
		sql.append("create_date < sysdate)) b ");
		sql.append("where ");
		sql.append("a.msg_id = b.\"msg_id\" and ");
		sql.append("a.create_date > sysdate -20 and ");
		sql.append("a.create_date < (sysdate - (1/(24*60*60))*20) and ");
		sql.append("a.status = '0' ");

		List<Map<String, Object>> sms = jdbcTemplate.queryForList(sql.toString());

		return sms;

	}

	@Override
	@Transactional(readOnly = false)
	public void smsExceptionNotification() {
		Object[] mailList = baseMgr.queryByHql("from Option where code=? and menu.key=?", new Object[] {
				"smsExceptionNotification", "SystemValue" }, 0, 1);
		Option mailTo = (Option) mailList[0];

		Object[] offarray = baseMgr.queryByHql("from Option where code=? and menu.key=?", new Object[] {
				"smsExceptionNotificationOFF", "SystemValue" }, 0, 1);
		Option off = (Option) offarray[0];
		if ("1".equals(off.getMemo1())) {
			List<Map<String, Object>> smsList = getSmsExceptionData();
			if (smsList.size() > 0) {
				// 準備郵件內容
				Map<String, Object> mailContentParameters = new HashMap<String, Object>();
				mailContentParameters.put("smsList", smsList);
				Mail notification = templateService.formatToMail(VM_SMS_EXCEPTION_NOTIFICATION, mailContentParameters);

				notification.setTo(mailTo.getMemo1());
				mailService.save(notification);
			}
		}
	}

}
